﻿///////////////////////////////////////////////////////////////////////////////
// File:        Queue.hpp
// Author:      671643387@qq.com
// Description:
///////////////////////////////////////////////////////////////////////////////

#ifndef NIO_BASE_QUEUE_HPP_
#define NIO_BASE_QUEUE_HPP_

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif

#include <deque>
#include <boost/noncopyable.hpp>
#include <nio/base/LockGuard.hpp>

namespace nio
{
    namespace base
    {
        template<typename T, typename LOCK, typename STORAGE = std::deque<T> >
        class Queue : public boost::noncopyable
        {
        public:
            Queue(void)
                : storage_()
                , lock_()
            {
            }

            explicit Queue(const Queue& queue)
                : storage_(queue)
                , lock_()
            {
            }

            explicit Queue(int size)
                : storage_(size)
                , lock_()
            {
            }

            Queue(const Queue& queue, int size)
                : storage_(queue, size)
                , lock_()
            {
            }

            ~Queue(void)
            {

            }

            T& front(void)
            {
                LockGuard<LOCK> guard(lock_);
                return storage_.front();
            }

            T& back(void)
            {
                LockGuard<LOCK> guard(lock_);
                return storage_.back();
            }

            void push_back(T& x)
            {
                LockGuard<LOCK> guard(lock_);
                storage_.push_back(x);
            }

            void push_front(T& x)
            {
                LockGuard<LOCK> guard(lock_);
                storage_.push_front(x);
            }

            void pop_back(void)
            {
                LockGuard<LOCK> guard(lock_);
                return storage_.pop_back();
            }

            void pop_front(void)
            {
                LockGuard<LOCK> guard(lock_);
                return storage_.pop_front();
            }

            bool empty(void)
            {
                LockGuard<LOCK> guard(lock_);
                return storage_.empty();
            }

            template<typename CHECKER>
            bool next(CHECKER& checker, T& x)
            {
                LockGuard<LOCK> guard(lock_);
                if (storage_.empty())
                    return false;

                x = storage_.front();
                if (!checker.check(x))
                    return false;

                storage_.pop_front();
                return true;
            }

        private:
            STORAGE storage_;
            LOCK lock_;
        };
    }
}

#endif //NIO_BASE_QUEUE_HPP_
